/**
 * @file calendar.h
 * @brief 农历与公历转换及日历显示功能的头文件
 * @details 提供农历公历互查、月历显示、节气计算等功能
 */

#ifndef __CALENDAR_H__
#define __CALENDAR_H__

#include<stdbool.h>
#include"..\..\include\system\system_time.h"

/**
 * @struct GREDATE
 * @brief 公历日期结构体
 * @details 用于存储公历日期相关信息，包含年、月、日以及相对于基准的天数（JDN）。
 */
typedef struct {
    int year;           /**< 公历年 */
    int month;          /**< 公历月，取值范围为1 - 12 */
    int day;            /**< 公历日，取值范围为1 - 31 */
    int baseDays;       /**< JDN，即相对于基准的天数 */
}GREDATE;

/**
 * @struct LUNARDATE
 * @brief 农历日期结构体
 * @details 用于存储农历日期相关信息，包括农历年、月、日、是否为闰月标志以及当月天数。
 */
typedef struct {
    int year;      /**< 农历年 */
    int month;          /**< 农历月，取值范围为1 - 12 */
    int day;            /**< 农历日，取值范围为1 - 30 */
    bool isLeapMonth;    /**< 闰月标志，true表示是闰月，false表示不是闰月 */
    int daysOfMonth; /**< 当月天数，用于标识大月或小月 */
}LUNARDATE;

/**
 * @brief 公历转农历
 * @param gre_date 输入的公历日期结构体，包含要转换的公历日期信息。
 * @param p_lunar_date 输出的农历日期结构体指针，用于存储转换后的农历日期信息。
 */
void GreToLunar(GREDATE gre_date,LUNARDATE *p_lunar_date);

/**
 * @brief 农历转公历
 * @param LunarDate 输入的农历日期结构体，包含要转换的农历日期信息。
 * @param p_gre_date 输出的公历日期结构体指针，用于存储转换后的公历日期信息。
 */
void LunarToGre(LUNARDATE LunarDate,GREDATE *p_gre_date);

/**
 * @brief 获取指定月份的天数
 * @param year 年份
 * @param month 月份
 * @param mode 模式标志，false表示公历模式，true表示农历模式
 * @param bLeap 是否为闰月标志，仅在农历模式下有效，true表示是闰月，false表示不是闰月
 * @return 当月的天数，如果输入错误（如在无闰月年份指定闰月等情况）可能返回 -1
 */
int GetDaysOfMonth(int year, int month, bool mode, bool bLeap);

/**
 * @brief 使用蔡氏公式计算星期几
 * @param year 年份
 * @param month 月份
 * @param day 日期
 * @return 计算得到的星期数，0表示星期日，1表示星期一，以此类推
 */
int ZellerWeek(int year,int month,int day);

/**
 * @brief 显示指定年月的日历
 * @param gre_date 包含公历日期信息的结构体，用于确定要显示日历的年月。
 */
void ShowCalendar(GREDATE gre_date);

/**
 * @brief 计算基准日
 * @param year 年份
 * @param month 月份
 * @param day 日期
 * @return 相对于基准的天数
 */
int JDNBaseDay(int year, int month, int day);

/**
 * @brief 取整函数
 * @param v 待取整的数值
 * @return 取整后的结果，对于负数，会向下取整
 */
int GetInteger(double v);

/**
 * @brief 获取小数部分
 * @param n 待处理的数值
 * @return 该数值的小数部分的值
 */
double GetDecimal(double n);

/**
 * @brief 判断闰年
 * @param nYear 待判断的年份
 * @return true表示该年份是闰年，false表示该年份是平年
 */
bool IsLeapYear(int nYear);

/**
 * @brief 将小数日转换为公历日期
 * @param n 小数日，通常是节气相关的小数表示
 * @return 精确的公历日期结构体，包含年、月、日、时、分、秒、毫秒以及星期等信息
 */
LONGTIME GetDate(double n);

#endif